import threading
from datetime import datetime
import os
from pickle import FALSE

from django.db.models import Prefetch, F
from django.http import HttpResponse
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.tokens import RefreshToken
import pandas as pd
from django.conf import settings
from django.db import transaction
from django.db.models import Count
from django.utils import timezone
from django.db.models.functions import TruncDate

from .models import User, Goods, Inventory, Customer, SalesOrder, Report, SaleDetail
from .serializers import UserSerializer, GoodsSerializer, InventorySerializer, CustomerSerializer, SalesOrderSerializer, \
    ReportSerializer
from rest_framework.views import APIView
from django.utils import timezone


class UserRegistrationView(APIView):
    """
    注册视图
    """

    def post(self, request):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class CustomLoginView(APIView):
    """
    自定义登录视图，用于接收用户名和密码并返回 JWT token。
    """

    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')

        try:
            user = User.objects.get(username=username)
            if user.check_password(password):
                refresh = RefreshToken.for_user(user)
                access_token = str(refresh.access_token)
                refresh_token = str(refresh)

                return Response({
                    "access": access_token,
                    "refresh": refresh_token,
                    "user_id": user.id,
                    "username": user.username,
                    "email": user.email,
                    "role": user.role  # 返回用户角色
                }, status=status.HTTP_200_OK)
            else:
                return Response({"error": "Invalid credentials"}, status=status.HTTP_401_UNAUTHORIZED)
        except User.DoesNotExist:
            return Response({"error": "Invalid credentials"}, status=status.HTTP_401_UNAUTHORIZED)


class UserViewSet(viewsets.ModelViewSet):
    """
    用户视图集
    """
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def update(self, request, *args, **kwargs):
        # 获取要更新的用户实例
        instance = self.get_object()

        # 只允许修改用户名和角色
        serializer = self.get_serializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)

        # 检查角色字段是否有效
        if 'role' in serializer.validated_data:
            if serializer.validated_data['role'] not in ['manager', 'user']:
                raise ValidationError("角色字段只能是 'manager' 或 'user'。")

        # 更新用户
        self.perform_update(serializer)

        return Response(serializer.data)


class GoodsViewSet(viewsets.ModelViewSet):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 获取货物id
        goods_id = serializer.validated_data.get('goods_id')
        # 查询库存信息
        try:
            inventory = Inventory.objects.get(goods_id=goods_id)
        except Inventory.DoesNotExist:
            return Response({"error": "库存记录不存在"}, status=status.HTTP_404_NOT_FOUND)

        # 检查 current_quantity 和 total_inventory
        if inventory.current_quantity == 0:
            if inventory.total_inventory == 0:
                return Response({"error": "货物未进货，新增失败"}, status=status.HTTP_400_BAD_REQUEST)
        elif inventory.total_inventory - inventory.current_quantity < 0:
            return Response({"error": "进货总数量小于上架数量，请检查数据库"},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        # 保存数据
        self.perform_create(serializer)
        print("保存的数据:", serializer.data)  # 打印保存的数据
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    @action(detail=True, methods=['GET'], url_path="update_shelves")
    def update_shelves(self, request, pk=None):
        goods = self.get_object()

        # 获取前端传递的参数 is_shelves
        is_shelves = request.GET.get('is_shelves', 'false').lower() == 'true'
        quantity = int(request.GET.get('quantity', 0))

        try:
            # 查询库存信息
            inventory = Inventory.objects.get(goods=goods)

            if is_shelves:
                # 上架操作
                if quantity <= 0:
                    return Response({"error": "上架数量必须大于0"}, status=status.HTTP_400_BAD_REQUEST)
                if inventory.current_quantity < quantity:
                    return Response({"error": f"库存不足，当前库存为 {inventory.current_quantity}"},
                                    status=status.HTTP_400_BAD_REQUEST)

                # 更新库存
                inventory.current_quantity -= quantity
                goods.on_shelves = True
                goods.save()
                inventory.save()

                return Response(
                    {"message": f"商品 {goods.goods_name} 已上架 {quantity} 件，剩余库存 {inventory.current_quantity}"},
                    status=status.HTTP_200_OK)
            else:
                # 下架操作
                if quantity <= 0:
                    return Response({"error": "下架数量必须大于0"}, status=status.HTTP_400_BAD_REQUEST)
                if inventory.current_quantity + quantity > inventory.total_inventory:
                    return Response({"error": f"下架数量超出总库存限制，总库存为 {inventory.total_inventory}"},
                                    status=status.HTTP_400_BAD_REQUEST)

                # 更新库存
                inventory.current_quantity += quantity
                goods.on_shelves = False
                goods.save()
                inventory.save()

                return Response(
                    {"message": f"商品 {goods.goods_name} 已下架 {quantity} 件，剩余库存 {inventory.current_quantity}"},
                    status=status.HTTP_200_OK)
        except Inventory.DoesNotExist:
            return Response({"error": "库存记录不存在"}, status=status.HTTP_404_NOT_FOUND)

    @action(detail=True, methods=['POST'], url_path="change_goods")
    def change_goods(self, request, pk=None):
        goods = self.get_object()
        # 获取前端传递的名称和价格
        name = request.data.get('name')
        price = request.data.get('price')

        # 验证参数
        if not name or not price:
            return Response({"error": "名称和价格都是必填字段"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            # 更新商品名称和价格
            goods.goods_name = name
            goods.price = float(price)
            goods.save()

            # 返回成功响应
            serializer = self.get_serializer(goods)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


def generate_inventory_report_task(user_id):
    try:
        # 获取所有库存数据
        inventories = Inventory.objects.all()
        inventory_data = [
            {
                '名称': inventory.goods.goods_name,
                '库存数量': inventory.current_quantity,
                '总数量': inventory.total_inventory,
                '上架数量': inventory.total_inventory - inventory.current_quantity,
                '最小警报值': inventory.min_quantity_alert
            }
            for inventory in inventories
        ]

        # 创建 DataFrame
        df = pd.DataFrame(inventory_data)

        # 保存到 Excel 文件
        report_date = datetime.now().strftime('%Y%m%d%H%M%S')
        file_name = f"inventory_report_{report_date}.xlsx"
        report_dir = os.path.join(settings.BASE_DIR, 'inventory_reports')
        os.makedirs(report_dir, exist_ok=True)
        file_path = os.path.join(report_dir, file_name)
        df.to_excel(file_path, index=False)

        # 创建 Report 记录
        with transaction.atomic():
            report = Report.objects.create(
                report_type='inventory',
                report_date=datetime.now(),
                generated_by_id=user_id,
                file_path=file_path,
                status='generated'
            )

        return report.id
    except Exception as e:
        raise e


class InventoryViewSet(viewsets.ModelViewSet):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    queryset = Inventory.objects.all()
    serializer_class = InventorySerializer

    @action(detail=False, methods=['GET'], url_path='generate_inventory_report')
    def generate_inventory_report(self, request):
        # 启动一个线程来处理报表生成
        thread = threading.Thread(target=generate_inventory_report_task, args=(request.user.id,))
        thread.start()
        return Response({'message': '报表生成任务已启动，请稍后查看状态'}, status=status.HTTP_202_ACCEPTED)

    @action(detail=False, methods=['POST'], url_path='receive_goods')
    def receive_goods(self, request):
        # 确保用户有权限执行此操作
        if not request.user.is_authenticated:
            return Response({"error": "You are not authenticated"}, status=status.HTTP_401_UNAUTHORIZED)

        goods_name = request.data.get('goods_name')
        quantity = request.data.get('quantity', 0)
        unit = request.data.get('unit', '')  # 新增字段
        price = request.data.get('price', 0)  # 新增字段
        description = request.data.get('description', '')  # 新增字段

        try:
            quantity = int(quantity)
            if quantity <= 0:
                raise ValueError("数量必须大于0")

            # 获取或创建商品
            defaults = {
                'created_at': timezone.now(),
                'unit': unit,  # 新增字段
                'price': price,  # 新增字段
                'description': description,  # 新增字段
            }
            goods, created = Goods.objects.get_or_create(goods_name=goods_name, defaults=defaults)

            # 获取或创建库存
            inventory, inv_created = Inventory.objects.get_or_create(goods=goods, defaults={'min_quantity_alert': 10})

            # 更新库存
            inventory.current_quantity += quantity
            inventory.total_inventory += quantity
            inventory.save()

            return Response({"message": f"成功添加了 {quantity} 个 {goods_name} 商品。库存已更新！"},
                            status=status.HTTP_200_OK)
        except Goods.DoesNotExist:
            return Response({"error": f"商品 {goods_name} 不存在。"}, status=status.HTTP_404_NOT_FOUND)
        except ValueError as ve:
            return Response({"error": str(ve)}, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=False, methods=['GET'], url_path='alerts')
    def alerts(self, request):
        # 查询 current_quantity < min_quantity_alert 的数据
        alerts = Inventory.objects.filter(current_quantity__lt=F('min_quantity_alert'))

        # 序列化查询结果
        serializer = self.get_serializer(alerts, many=True)

        return Response(serializer.data)

    @action(detail=False, methods=['GET'], url_path='alerts_count')
    def alerts_count(self, request):
        # 查询 current_quantity <= min_quantity_alert 的数据数量
        count = Inventory.objects.filter(current_quantity__lte=F('min_quantity_alert')).count()
        return Response({'count': count})


class CustomerViewSet(viewsets.ModelViewSet):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer

    @action(detail=False, methods=['GET'], url_path='stats_customer')
    def stats_customer(self, request):
        # 获取最近30天的数据
        today = timezone.now().date()
        start_date = today - timezone.timedelta(days=30)

        # 按日期分组，统计每日新增客户数量
        stats = (
            Customer.objects
            .filter(created_at__gte=start_date)
            .annotate(date=TruncDate('created_at'))
            .values('date')
            .annotate(new_customers=Count('id'))
            .order_by('date')
        )

        # 将结果转换为列表格式
        data = [
            {
                'date': stat['date'].strftime('%Y-%m-%d'),
                'new_customers': stat['new_customers']
            }
            for stat in stats
        ]

        return Response(data, status=status.HTTP_200_OK)



def generate_sales_report_task(user_id):
    try:
        # 获取所有销售订单数据，并联表查询customer和sale_details
        sales_orders = SalesOrder.objects.select_related('customer').prefetch_related(
            Prefetch('saledetail_set', queryset=SaleDetail.objects.select_related('goods'))
        ).all()

        # 准备报表数据
        sales_data = []
        for order in sales_orders:
            # 获取客户名称
            customer_name = order.customer.customer_name if order.customer else '未知客户'

            # 获取订单详情和货物信息
            order_details = []
            for detail in order.saledetail_set.all():
                goods = detail.goods
                order_details.append({
                    '货物名称': goods.goods_name if goods else '未知货物',
                    '数量': detail.quantity,
                    '单价': detail.unit_price
                })

            # 将 datetime 对象转换为字符串格式，去除时区信息
            order_date = order.order_date.astimezone().replace(tzinfo=None).strftime('%Y-%m-%d')
            created_at = order.created_at.astimezone().replace(tzinfo=None).strftime('%Y-%m-%d %H:%M:%S')

            # 构造销售订单数据
            sales_data.append({
                '订单ID': order.id,
                '订单日期': order_date,
                '总金额': order.total_amount,
                '状态': order.status,
                '客户ID': order.customer_id,
                '客户名称': customer_name,
                '订单详情': order_details,
                '创建时间': created_at
            })

        # 创建 DataFrame
        df = pd.DataFrame(sales_data)

        # 保存到 Excel 文件
        report_date = datetime.now().strftime('%Y%m%d%H%M%S')
        file_name = f"sales_report_{report_date}.xlsx"
        report_dir = os.path.join(settings.BASE_DIR, 'sales_reports')
        os.makedirs(report_dir, exist_ok=True)
        file_path = os.path.join(report_dir, file_name)
        df.to_excel(file_path, index=False)

        # 创建 Report 记录
        with transaction.atomic():
            report = Report.objects.create(
                report_type='sales',
                report_date=datetime.now(),
                generated_by_id=user_id,
                file_path=file_path,
                status='generated'
            )

        return report.id
    except Exception as e:
        raise e


class SalesOrderViewSet(viewsets.ModelViewSet):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    queryset = SalesOrder.objects.all()
    serializer_class = SalesOrderSerializer

    def create(self, request, *args, **kwargs):
        request.data['order_date'] = datetime.now().strftime('%Y-%m-%d')  # 当前日期
        request.data['status'] = 'pending'  # 默认状态
        print(request.data)
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        print(serializer.validated_data)

        # 获取商品 ID 和数量
        goods_id = request.data['sales_detail']['goods']
        quantity = request.data['sales_detail']['quantity']

        try:
            inventory = Inventory.objects.get(goods_id=goods_id)
            if inventory.total_inventory - inventory.current_quantity < quantity:
                return Response({"error": "货架数量不足，请上架货物"}, status=status.HTTP_400_BAD_REQUEST)
            order = serializer.save()

            # 创建销售订单详情
            SaleDetail.objects.create(
                quantity=quantity,
                unit_price=request.data['sales_detail']['unit_price'],
                goods_id=goods_id,
                order_id=order.id
            )

            # 更新库存
            inventory.total_inventory -= quantity
            inventory.save()

            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
        except Inventory.DoesNotExist:
            return Response({"error": "库存记录不存在"}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()

        # 只允许更新 status 字段
        request.data['status'] = request.data.get('status', instance.status)
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        return Response(serializer.data)

    @action(detail=False, methods=['GET'], url_path='generate_sales_report')
    def generate_sales_report(self, request):
        thread = threading.Thread(target=generate_sales_report_task, args=(request.user.id,))
        thread.start()
        return Response({'message': '报表生成任务已启动，请稍后查看状态'}, status=status.HTTP_202_ACCEPTED)


class ReportViewSet(viewsets.ModelViewSet):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    queryset = Report.objects.all()
    serializer_class = ReportSerializer

    @action(detail=False, methods=['GET'], url_path='inventory')
    def list_inventory(self, request):
        queryset = Report.objects.filter(report_type='inventory')
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['GET'], url_path='sales')
    def list_sales(self, request):
        queryset = Report.objects.filter(report_type='sales')
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['POST'], url_path='download_inventory_report')
    def download_inventory_report(self, request):
        file_path = request.data.get('file_path')
        if not file_path:
            return Response({"error": "文件路径不能为空"}, status=status.HTTP_400_BAD_REQUEST)

        if not os.path.exists(file_path):
            return Response({"error": "文件不存在"}, status=status.HTTP_404_NOT_FOUND)

        with open(file_path, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/octet-stream')
            response['Content-Disposition'] = f'attachment; filename="{os.path.basename(file_path)}"'
            return response